package com.pyip.reggie.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pyip.reggie.Entity.Category;
import com.pyip.reggie.Entity.Dish;
import com.pyip.reggie.Entity.DishFlavor;
import com.pyip.reggie.common.R;
import com.pyip.reggie.dto.DishDto;
import com.pyip.reggie.mapper.DishMapper;
import com.pyip.reggie.service.CategoryService;
import com.pyip.reggie.service.DishFlavorService;
import com.pyip.reggie.service.DishService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {

    @Autowired
    private DishFlavorService dishFlavorService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 新增菜品，同时保存对应的口味数据
     * @param dishDto
     * @return
     */
    @Transactional
    @Override
    public Boolean saveWithFlavor(DishDto dishDto) {
        // 新加菜品，要更新redis中的数据
        // 方案一：清理所有菜品的缓存数据(测试通过）
//        Set keys = redisTemplate.keys("Category_*");
//        redisTemplate.delete(keys);

//        方案二：清理指定菜品的缓存数据
        Long categoryId = dishDto.getCategoryId();
        // 新加的菜品属于这个categoryId，所以只需要清理这个下面的数据就可以了（如果存在缓存）（测试通过）
//        String key = "Category_dish_" + dish.getCategoryId() + "_" + dish.getStatus();
        String key = "Category_dish_" + categoryId + "_1";
        redisTemplate.delete(key);

        baseMapper.insert(dishDto);

        // 查找dishDto的菜品id
        Long dishId = dishDto.getId();
        // 菜品口味
        List<DishFlavor> flavors = dishDto.getFlavors();
        flavors = flavors.stream().map((item)->{
            item.setDishId(dishId);
            return item;
        }).collect(Collectors.toList());

        // 保存菜品口味到菜品口味表dish_flavor中
        return dishFlavorService.saveBatch(flavors);
    }

//     TODO 已完成

    @Override
    public R<Page<DishDto>> getPage(int page, int pageSize, String name) {
        Page<Dish> pageInfo = new Page<>(page,pageSize);
        Page<DishDto> dishDtoPage = new Page<>();

        LambdaQueryWrapper<Dish> dlqw = new LambdaQueryWrapper<>();
        dlqw.like(name!=null,Dish::getName,name);
        dlqw.orderByDesc(Dish::getUpdateTime);
        // 执行分布查询
        baseMapper.selectPage(pageInfo,dlqw);

        BeanUtils.copyProperties(pageInfo,dishDtoPage,"records");

        List<DishDto> list = pageInfo.getRecords().stream().map((item) -> {
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(item,dishDto);
            Long categoryId = item.getCategoryId();
            LambdaQueryWrapper<Category> clqw = new LambdaQueryWrapper<Category>();
            clqw.eq(Category::getId,categoryId);
            Category one = categoryService.getOne(clqw);
            // One有可能不存在
            if(one != null){
                dishDto.setCategoryName(one.getName());
            }
            return dishDto;
        }).collect(Collectors.toList());

        dishDtoPage.setRecords(list);
        return R.success(dishDtoPage);
    }

    /**
     *
     * @param id
     * @return
     */
    @Override
    public R<DishDto> getByDishId(Long id) {
        // 查找到相关dish
        Dish dish = baseMapper.selectById(id);
        // 通过dish的id查找dishFlavor相关信息
        LambdaQueryWrapper<DishFlavor> dflqw = new LambdaQueryWrapper<>();
        dflqw.eq(DishFlavor::getDishId,id);
        List<DishFlavor> list = dishFlavorService.list(dflqw);

        // 将dish和dishFlavor信息封装到dishDto中
        DishDto dishDto = new DishDto();
        BeanUtils.copyProperties(dish,dishDto);
        dishDto.setFlavors(list);
        return dishDto == null ? R.error("查无信息") : R.success(dishDto);
    }


    @Transactional
    @Override
    public R<String> updateDishAndDishFlavor(DishDto dishDto) {
        // 先根据dishDto更新dish，再删除对应的dishFlavor信息，再添加相应的dishFlavor信息
        // 同样有两种方法
        // 清空所有缓存
        // 清空当前dish的categoryId下的缓存

        // 方案一：清理所有菜品的缓存数据(测试通过）
//        Set keys = redisTemplate.keys("Category_*");
//        redisTemplate.delete(keys);

//        方案二：清理指定菜品的缓存数据
        Long categoryId = dishDto.getCategoryId();
        // 新加的菜品属于这个categoryId，所以只需要清理这个下面的数据就可以了（如果存在缓存）（测试通过）
//        String key = "Category_dish_" + dish.getCategoryId() + "_" + dish.getStatus();
        String key = "Category_dish_" + categoryId + "_1";
        redisTemplate.delete(key);

        // 没有缓存正常运行
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishDto,dish);
        baseMapper.updateById(dish);
        // 更新dish表成功
        // 删除对应的dishFlavor表信息
        LambdaQueryWrapper<DishFlavor> dlqw = new LambdaQueryWrapper<>();
        dlqw.eq(DishFlavor::getDishId,dish.getId());
        dishFlavorService.remove(dlqw);
        // 添加对应的dishFlavor表信息
        List<DishFlavor> flavors = dishDto.getFlavors();
        // 每个flavors中都没有dishId的信息，要添加dishid的信息进行绑定
        flavors = flavors.stream().map((item)->{
            item.setDishId(dish.getId());
            return item;
        }).collect(Collectors.toList());


        return dishFlavorService.saveBatch(flavors) ? R.success("更新成功") : R.error("更新信息失败");
    }

    // 缓存菜品（根据categoryId)
    @Override
    public R<List<DishDto>> getAllDishByCategoryId(Dish dish) {
        List<DishDto> dishDtos = null;
        //A. 根据分类ID查询，查询目前正在启售的菜品列表 (已实现)
        //B. 遍历菜品列表，并查询菜品的分类信息及菜品的口味列表
        //C. 组装数据DishDto，并返回

        // 动态构造key，如果存在，则直接返回，反之，进行添加
        String key = "Category_dish_" + dish.getCategoryId() + "_1";
        // 查找redis
        dishDtos = (List<DishDto>) redisTemplate.opsForValue().get(key);

        if(dishDtos != null){
            // redis中存在，直接返回数据
            return R.success(dishDtos);
        }

        LambdaQueryWrapper<Dish> dlqw = new LambdaQueryWrapper<>();
        dlqw.eq(dish.getCategoryId() != null,Dish::getCategoryId,dish.getCategoryId());
        // 所在在售商品
        dlqw.eq(Dish::getStatus,1);
        dlqw.orderByAsc(Dish::getSort);
        List<Dish> dishes = baseMapper.selectList(dlqw);

        dishDtos = dishes.stream().map(
                (item)->{
                    DishDto dishDto = new DishDto();
                    BeanUtils.copyProperties(item,dishDto);

                    Long categoryId = item.getCategoryId();
                    // 根据id查询分类对象
                    Category category = categoryService.getById(categoryId);
                    if(category != null){
                        String categoryName = category.getName();
                        dishDto.setCategoryName(categoryName);
                    }
                    // 当前菜品的id
                    Long dishId = item.getId();
                    LambdaQueryWrapper<DishFlavor> dflqw = new LambdaQueryWrapper<>();
                    dflqw.eq(DishFlavor::getDishId,dishId);
                    List<DishFlavor> dishFlavorList = dishFlavorService.list(dflqw);
                    dishDto.setFlavors(dishFlavorList);

                    return dishDto;
                }
        ).collect(Collectors.toList());

        // redis中不存在，保存数据 (保存一小时）
        redisTemplate.opsForValue().set(key,dishDtos,60l, TimeUnit.MINUTES);

        // 返回查询的信息
        return R.success(dishDtos);
    }
}
